home *** CD-ROM | disk | FTP | other *** search
- _RECURSIVE IMAGES_
- by Steven Janke
-
-
- [LISTING ONE]
-
- PROGRAM RECURTRE;
- uses graph;
- var inc,firstdirection :real;
- gd,gm,depth,scale :integer;
- startx,starty :integer;
- xasp,yasp :word;
- asp :real;
- const pi:real=3.14159;
- procedure TREE(X,Y:integer; DIR:real; LEVEL:integer);
- var xnew,ynew:integer;
- begin
- if level>0 then {At level zero, recursion ends.}
- begin
- xnew:= round(level*scale*cos(dir))+x; {Multiplying by level }
- ynew:= round(asp*level*scale*sin(dir))+y; {varies the branch size.}
- if level<3 then setcolor(green) else setcolor(brown); {Green leaves}
- line(x,y,xnew,ynew);
- TREE(xnew,ynew,dir+random*inc,level-1); {Two recursive calls - one}
- TREE(xnew,ynew,dir-random*inc,level-1); {for each new branch.}
- end;
- end;
- procedure INIT;
- begin
- firstdirection:=-pi/2; {Negative since y increases down the screen.}
- inc:=pi/4;
- scale:=5;
- depth:=10;
- startx:=round(GETMAXX/2); starty:=round(0.75*GETMAXY);
- GETAspectRatio(xasp,yasp); asp:=xasp/yasp; {Find aspect ratio}
- end;
- BEGIN
- gd:=detect;
- initgraph(gd,gm,'\tp\units'); {Graphic drivers kept in \tp\units.}
- cleardevice; randomize;
- INIT;
- TREE(startx, starty, firstdirection, depth);
- readln;
- closegraph;
- END.
-
-
-
- [LISTING TWO]
-
- PROGRAM IFSDRAW; {Random Algorithm for drawing IFS attractor.}
- uses graph;
- var gd, gm :integer; {For graphics initialization}
- xoff, yoff :integer; {Offset to determine origin}
- xsc, ysc :real; {Scale variables}
- n, cl :integer; {Index variable, color variable}
- x,y,asp :real; {Starting point and aspect ratio}
- xasp,yasp :word; {Used to determine aspect ratio}
- const {Normally, these constants would be read from a data file. They
- are listed as constants here only for illustration. These
- particular transformations form an IFS for Sierpinski's triangle.}
- Totaltran:integer=3;
- CT:array[1..3,1..7] of real =
- {Format: a, b, c, d, e, f, probability}
- (( 0.5, 0, 0, 0, 0.5, 0, 0.33),
- ( 0.5, 0, 100, 0, 0.5, 0, 0.33),
- ( 0.5, 0, 50, 0, 0.5, -100, 0.33));
- procedure SETPROB;
- {To get a running sum of the probabilities for random number generation.}
- var i:integer;
- sum:real;
- begin
- sum:=0;
- for i:=1 to totaltran-1 do
- begin sum:=sum+CT[i,7]; CT[i,7]:=sum; end;
- CT[totaltran,7]:=1; {This is set to 1 to avoid any round-off problem.}
- end;
- procedure MAKETRAN;
- {Determine which transformation is next and then apply it.}
- var nx,ny:real;
- s:integer;
- function FINDTRAN:integer;
- {Return a random number between 1 and the number of transformations.}
- var i:integer;
- w:real;
- begin
- w:=random; i:=1;
- while w>CT[i,7] do i:=i+1;
- FINDTRAN:=i;
- end;
- begin
- S:=FINDTRAN;
- NX:=CT[S,1]*X + CT[S,2]*Y + CT[S,3];
- NY:=CT[S,4]*X + CT[S,5]*Y + CT[S,6];
- X:=NX; Y:=NY;
- end;
- procedure INIT;
- begin
- XSC:=1; YSC:=1; {Scale factors}
- XOFF:=round(GETMAXX/2); YOFF:=round(GETMAXY/2); {Determines origin}
- X:=0; Y:=0; {Starting point}
- cl:=white;
- GETAspectRatio(xasp,yasp); {BGI function for determining aspect ratio}
- asp:=xasp/yasp;
- end;
- BEGIN
- gd:=detect; initgraph(gd,gm,' '); cleardevice;
- INIT; SETPROB;
- for N:=1 to 5000 do
- begin
- MAKETRAN;
- putpixel(round(X*XSC)+XOFF, (round(asp*Y*YSC)+YOFF),cl);
- end;
- readln;
- closegraph;
- END.
-
-
-
-
- [LISTING THREE]
-
- PROGRAM IFS; {ITERATED FUNCTION SYSTEM DESIGNER}
- uses graph,crt;
- type matrix = array[1..2,1..3] of real;
- var points:array[1..100,1..2] of integer; {Points and Pts store vertices}
- pts:array[1..100,1..2] of real; {of main figure.}
- gd,gm: integer; {For graphics initialization.}
- cp:integer; {Total number of vertices in main figure.}
- xoff,yoff:integer; {Offset for main figure placement.}
- asp,xt,yt:real; {Aspect ratio and offsets for transformation.}
- select:boolean; {For menu selection.}
- tran:matrix; {Coefficients of current transformation.}
- tranlist: array[1..50] of matrix; {List of transformations}
- totaltran:integer; {Total number of transformations.}
- procedure APPLYTRAN; {--------------------------------------------}
- {Applies the current transformation to the vertices of main figure.}
- var i:integer;
- a:real;
- begin
- for i:=1 to cp do
- begin
- a:=tran[1,1]*pts[i,1]+tran[1,2]*pts[i,2];
- pts[i,2]:=tran[2,1]*pts[i,1]+tran[2,2]*pts[i,2];
- pts[i,1]:=a;
- end;
- end;
- procedure INIT; {-------------------------------------------------}
- var xasp,yasp:word;
- begin
- cp:=1;
- xoff:=round(GETMAXX/2); yoff:=round(GETMAXY/2);
- xt:=0; yt:=0;
- GETASPECTRATIO(Xasp,Yasp); asp:=xasp/yasp;
- totaltran:=0;
- end;
- procedure INITTRAN; {---------------------------------------------}
- begin
- tran[1,1]:=1; tran[1,2]:=0; tran[2,1]:=0; tran[2,2]:=1;
- end;
- procedure SAVETRAN(n:integer); {----------------------------------}
- begin
- tranlist[n]:=tran;
- tranlist[n,1,3]:=xt; tranlist[n,2,3]:=yt;
- xt:=0; yt:=0;
- end;
- procedure CONVPOINTS; {-------------------------------------------}
- {Converts screen coordinates in Points to world coordinates in Pts.}
- var i:integer;
- begin
- for i:=1 to cp do
- begin
- pts[i,1]:=points[i,1]-xoff;
- pts[i,2]:=(points[i,2]-yoff)/asp;
- end;
- end;
- procedure DRAWFIG(col:integer); {---------------------------------}
- var i,holdcol:integer;
- begin
- holdcol:=getcolor; setcolor(col);
- for i:=1 to cp-1 do
- line(round(pts[i,1]+xoff+xt),round(pts[i,2]*asp+yoff+yt*asp),
- round(pts[i+1,1]+xoff+xt),round(pts[i+1,2]*asp+yoff+yt*asp));
- setcolor(holdcol);
- end;
- procedure REDRAW(N:integer); {-------------------------------------}
- {Redraws orignial figure plus the results of each transformation.}
- {Transformation number N is not drawn.}
- var i:integer;
- begin
- xt:=0; yt:=0;
- cleardevice; CONVPOINTS; DRAWFIG(blue);
- for i:=1 to totaltran do
- if i<>n then
- begin
- CONVPOINTS; tran:=tranlist[i];
- xt:=tranlist[i,1,3]; yt:=tranlist[i,2,3];
- APPLYTRAN;
- DRAWFIG(red);
- end;
- xt:=0; yt:=0;
- end;
- procedure SCALE(xsize,ysize:real); {-------------------------------}
- {Changes the size of a figure.}
- var i,j:integer;
- begin
- for i:=1 to cp do
- begin pts[i,1]:=xsize*pts[i,1];
- pts[i,2]:=ysize*pts[i,2];
- end;
- for i:=1 to 2 do tran[1,i]:=xsize*tran[1,i];
- for i:=1 to 2 do tran[2,i]:=ysize*tran[2,i];
- end;
- procedure POSITION; {---------------------------------------------}
- {Positions figure as a new transformation is constructed.}
- var k:char;
- xx,yy:integer;
-
- procedure DIRECTIONS; {....................................}
- begin
- gotoxy(1,16); writeln('SCALE (S/W)');
- writeln('SCALEX (A/Q)');
- writeln('SCALEY (D/E)');
- writeln('ROTATE (R/F)');
- writeln('ROTATEX (T/G)');
- writeln('ROTATEY (Y/H)');
- writeln('REFLECT (X)');
- writeln('Use ARROWS to translate.');
- gotoxy(1,25); write('... Press Enter when finished ...');
- end;
- procedure REFLECT; {......................................}
- {Flips the figure around the line x=y.}
- var i:integer;
- xx:real;
- begin
- for i:=1 to cp do
- begin xx:=pts[i,1]; pts[i,1]:=pts[i,2]; pts[i,2]:=xx; end;
- xx:=tran[1,1]; tran[1,1]:=tran[2,1]; tran[2,1]:=xx;
- xx:=tran[1,2]; tran[1,2]:=tran[2,2]; tran[2,2]:=xx;
- end;
- procedure ROTATE(xangle,yangle:real); {...................}
- {Rotates the figure. If xangle and yangle are unequal, rotation}
- {is skewed.}
- var i,j:integer;
- a,b,xca,xsa,yca,ysa:real;
- begin
- xca:=cos(xangle); xsa:=sin(xangle);
- yca:=cos(yangle); ysa:=sin(yangle);
- for i:=1 to cp do
- begin
- a:=pts[i,1]*xca-pts[i,2]*ysa;
- pts[i,2]:=pts[i,1]*xsa+pts[i,2]*yca;
- pts[i,1]:=a;
- end;
- a:=tran[1,1]*xca-tran[2,1]*ysa;
- b:=tran[1,2]*xca-tran[2,2]*ysa;
- tran[2,1]:=tran[1,1]*xsa+tran[2,1]*yca;
- tran[2,2]:=tran[1,2]*xsa+tran[2,2]*yca;
- tran[1,1]:=a; tran[1,2]:=b;
- end;
- procedure WRITETRAN; {......................................}
- var i,j:integer;
- begin
- gotoxy(1,3); writeln('Current Transformation: ');
- for i:=1 to 2 do
- begin
- for j:=1 to 2 do
- begin
- gotoxy(1+(j-1)*10, 5+(i-1));
- writeln(tran[i,j]:7:2);
- end;
- gotoxy(21, 5+(i-1));
- if i=1 then writeln(xt:7:2) else writeln(yt:7:2);
- end;
- end;
- begin
- xx:=round(xt); yy:=round(asp*yt);
- WRITETRAN; DIRECTIONS;
- k:=readkey;
- while ord(k)<>13 do
- begin
- DRAWFIG(green);
- case ord(k) of
- 0: begin
- k:=readkey;
- case ord(k) of
- 72: yy:=yy-3;
- 77: xx:=xx+4;
- 80: yy:=yy+3;
- 75: xx:=xx-4;
- end;
- end;
- 83,115: scale(0.9,0.9); { S for decrease }
- 87,119: scale(1.1,1.1); { W for increase }
- 65,97 : scale(0.9,1); { A for x decrease }
- 68,100: scale(1,0.9); { D for y decrease }
- 81,113: scale(1.1,1); { Q for x increase }
- 69,101: scale(1,1.1); { E for y decrease }
- 82,114: rotate(0.1,0.1); { R for rotate cw }
- 70,102: rotate(-0.1,-0.1); { F for rotate ccw }
- 84,116: rotate(-0.1,0); { T for x rotate cw }
- 71,103: rotate(0.1,0); { G for x rotate ccw }
- 89,121: rotate(0,-0.1); { Y for y rotate cw }
- 72,104: rotate(0,0.1); { H for y rotate ccw }
- 88,120: reflect; { X to reflect in x=y }
- end;
- xt:=xx; yt:=yy/asp; DRAWFIG(green);
- WRITETRAN;
- k:=readkey;
- end;
- end;
- procedure SHAPE; {-------- SECTION I ------------------------------}
- {Sets up the main figure.}
- var i,j,er:integer;
- k:char;
- procedure BOX(x,y,col:integer); {..........................}
- var vs,hs,holdcol:integer;
- begin
- hs:=3; vs:=2; holdcol:=getcolor; setcolor(col);
- line(x-hs,y-vs,x+hs,y-vs);
- line(x+hs,y-vs,x+hs,y+vs);
- line(x+hs,y+vs,x-hs,y+vs);
- line(x-hs,y+vs,x-hs,y-vs);
- setcolor(holdcol);
- end;
- begin
- gotoxy(1,1); writeln('ITERATED FUNCTION SYSTEM DESIGNER');
- writeln('Section I: Draw outline of desired figure ....');
- gotoxy(1,23); writeln('Use arrows to position cursor.');
- writeln('Press P to place a vertex.');
- write('Press Enter when finished.');
- i:=xoff; j:=yoff; setwritemode(xorput);
- BOX(i,j,white);
- k:=readkey; er:=1; {Variable er used to determine when to draw box.}
- while ord(k)<>13 do
- begin
- case ord(k) of
- 0: begin if er=1 then BOX(i,j,white); er:=1;
- k:=readkey;
- case ord(k) of
- 72: j:=j-6;
- 77: i:=i+8;
- 80: j:=j+6;
- 75: i:=i-8;
- end;
- BOX(i,j,white);
- end;
- 80,112: begin er:=0; points[cp,1]:=i; points[cp,2]:=j;
- if cp>1 then begin setcolor(blue);
- line(points[cp-1,1],points[cp-1,2],
- points[cp,1], points[cp,2]);
- setcolor(white); end;
- cp:=cp+1;
- end;
- end;
- k:=readkey;
- end;
- points[cp,1]:=points[1,1]; points[cp,2]:=points[1,2];
- setcolor(blue);
- line(points[cp-1,1],points[cp-1,2],points[1,1],points[1,2]);
- setcolor(white); setwritemode(copyput);
- end;
- procedure MAKETRAN; {---------- SECTION II ------------------------}
- {Allows construction and alteration of transformations.}
- var nt,choice:integer;
- s,me:char;
- function MENUII:integer; {........................................}
- var xn:integer;
- begin
- gotoxy(1,1); writeln('1. Another Transformation');
- writeln('2. Next Transformation');
- writeln('3. Prepare to Draw');
- gotoxy(1,5); writeln('Select Number: '); me:=readkey;
- while (ord(me)<49) or (ord(me)>51) do me:=readkey;
- MENUII:=ord(me)-48;
- gotoxy(1,1);
- for xn:=1 to 5 do writeln(' ');
- end;
- begin
- gotoxy(1,1); writeln('Section II: Build Transformations ...');
- choice:=1; nt:=0;
- if totaltran<>0 then choice:=2;
- while choice<>3 do
- begin
- if choice=2 then
- begin nt:=nt+1;
- if nt>totaltran then nt:=1;
- REDRAW(nt);
- tran:=tranlist[nt];
- xt:=tranlist[nt,1,3]; yt:=tranlist[nt,2,3];
- end
- else begin INITTRAN; totaltran:=totaltran+1;
- nt:=totaltran;end;
- CONVPOINTS;
- if choice=2 then APPLYTRAN else SCALE(0.5,0.5);
- setwritemode(xorput);
- DRAWFIG(green);
- POSITION;
- setwritemode(copyput);
- SAVETRAN(NT);
- REDRAW(0);
- CHOICE:=MENUII;
- end;
- cleardevice;
- end;
- procedure GENERATE; {------------ SECTION III ---------------------}
- {Draw the resulting picture by applying transformations at random.}
- var xx,nm,wh,bd,cl,choice:integer;
- x,y:real;
- me:char;
- probs:array[1..50] of real;
-
- procedure ASSIGNPROB; {....................................}
- {Determines probability of each transformation.}
- var i:integer;
- s:real;
- begin
- for i:=1 to totaltran do
- begin
- tran:=tranlist[i];
- probs[i]:=abs(tran[1,1]*tran[2,2] - tran[1,2]*tran[2,1]);
- if probs[i]<0.02 then probs[i]:=0.02;
- end;
- s:=0; for i:=1 to totaltran do s:=s+probs[i];
- for i:=1 to totaltran do probs[i]:=probs[i]/s;
- s:=0; for i:=1 to totaltran do begin s:=s+probs[i]; probs[i]:=s; end;
- probs[i]:=1;
- end;
- function PICK:integer; {..................................}
- {Picks a transformation with designated probability distribution.}
- var j:integer;
- p:real;
- begin
- p:=random; j:=1;
- while p>probs[j] do j:=j+1;
- PICK:=j;
- end;
- procedure APPLY(w:integer); {..............................}
- {Applies chosen transformation to current point X,Y.}
- var z:real;
- begin
- tran:=tranlist[w];
- z:=tran[1,1]*X+tran[1,2]*Y;
- Y:=tran[2,1]*X+tran[2,2]*Y;
- X:=z+tran[1,3];
- Y:=Y+tran[2,3];
- end;
- procedure PUTIT(cc:integer); {.............................}
- begin
- if cl=0 then cc:=white;
- putpixel(round(X+xoff),round(Y*asp+yoff),cc);
- end;
- procedure MENUIII; {.......................................}
- var s:string;
- xx:integer;
- begin
- bd:=0;cl:=0;
- gotoxy(1,3); write('1. Border (Toggles)');
- gotoxy(25,3); writeln('Excluded');
- write('2. Color (Toggles)');
- gotoxy(25,4); writeln('No');
- writeln('3. Draw Image');
- writeln;writeln('Select Number: ');
- me:='5';
- while (ord(me)<>51) do
- begin
- me:=readkey;
- while (ord(me)<49) or (ord(me)>51) do me:=readkey;
- case ord(me) of
- 49: begin if bd=0 then begin bd:=1; s:='Included'; end
- else begin bd:=0; s:='Excluded'; end;
- gotoxy(25,3);write(s);
- end;
- 50: begin if cl=0 then begin cl:=1; s:='Yes';end
- else begin cl:=0; s:='No ';end;
- gotoxy(25,4);write(s);
- end;
- end;
- end;
- gotoxy(1,3);
- for xx:=1 to 5 do writeln(' ');
- end;
- begin
- cleardevice; ASSIGNPROB; randomize;
- gotoxy(1,1); writeln('Section III: Draw Image ... ');
- MENUIII;
- if bd=1 then begin CONVPOINTS; DRAWFIG(blue); end;
- nm:=3000; {Number of points to plotted in final image.}
- X:=0;Y:=0; {Initial point drawn.}
- PUTIT(7);
- for xx:=1 to nm do
- begin
- wh:=PICK; APPLY(wh); PUTIT((wh mod 7)+1);
- end;
- end;
- procedure FILESAVE;
- {To save transformations on disk.}
- var i:integer;
- tranfile:file of matrix;
- begin
- assign(tranfile, 'IFS.DAT');
- rewrite(tranfile);
- for i:=1 to totaltran do write(tranfile, tranlist[i]);
- close(tranfile);
- end;
- function MENUIV:boolean; {.......................................}
- var s:string;
- me:char;
- begin
- gotoxy(1,3); writeln('1. Return to Section II');
- writeln('2. Save transformations on file');
- writeln('3. Quit');
- writeln;writeln('Select Number: ');
- me:='2';
- while me='2' do
- begin
- me:=readkey;
- while (ord(me)<49) or (ord(me)>51) do me:=readkey;
- if me='2' then begin FILESAVE;
- gotoxy(1,9); writeln('DATA SAVED');
- end;
- end;
- if me='1' then MENUIV:=true else MENUIV:=false;
- end;
- BEGIN {----------------- Main Body ------------------------------}
- gd:=detect; initgraph(gd,gm,'');
- directvideo:=false; {Allows text using WRITE statements.}
- INIT; cleardevice;
- SHAPE; {... Section I ...}
- select:=true;
- while select do
- begin
- REDRAW(0);
- MAKETRAN; {... Section II ...}
- GENERATE; {... Section III ...}
- select:=MENUIV;
- end;
- cleardevice; closegraph;
- END.
-
-
-
-
- [LISTING FOUR]
-
- PROGRAM FOREST; {A mixture of two systems to produce a forest of ferns}
- uses graph;
- var n,xoff,yoff,gd,gm,cl: integer;
- xsc,ysc,x,y,bx,by,asp:real;
- xasp,yasp:word;
- const
- {CT holds the IFS for a fern}
- CT:array[1..4,1..7] of real =
- (( 0, 0, 0, 0, 0.16, 0, 0.02),
- ( 0.2,-0.26, 0, 0.23, 0.22, -24, 0.065),
- (-0.15, 0.28, 0, 0.26, 0.24, -6.6, 0.065),
- ( 0.85, 0.04, 0,-0.04, 0.85, -24, 0.85));
- {PL holds additional IFS functions to produce the forest}
- PL:array[1..2,1..6] of real =
- (( 0.8, 0, 80, 0, 0.8, -65),
- ( 0.8, 0, -80, 0, 0.8, -60));
- PROB:array[1..6] of real = (0.008, 0.034, 0.06, 0.4, 0.7, 1.0);
- procedure MAKETRAN;
- var nx,ny:real;
- s:integer;
- function FINDTRAN:integer;
- var i:integer;
- w:real;
- begin
- w:=random; I:=1;
- while w>PROB[i] do i:=i+1;
- FINDTRAN:=i;
- end;
- begin
- s:=FINDTRAN;
- if s<5 then {Generate another point in the fern.}
- begin
- nx:=CT[s,1]*x + CT[s,2]*y + CT[s,3];
- ny:=CT[s,4]*x + CT[S,5]*y + CT[s,6];
- x:=nx; y:=ny; bx:=x; by:=y;
- end
- else {Generate another point in the forest.}
- begin
- s:=s-4;
- nx:=PL[s,1]*bx + PL[s,2]*by + PL[s,3];
- ny:=PL[s,4]*bx + PL[s,5]*by + PL[s,6];
- bx:=nx; by:=ny;
- end;
- end;
- procedure INIT;
- begin
- xsc:=1.3; ysc:=1;
- xoff:=round(GETMAXX/2); yoff:=GETMAXY-50;
- x:=0; y:=0;
- bx:=0; by:=0;
- GETAspectRatio(xasp,yasp); asp:=xasp/yasp;
- end;
- BEGIN
- gd:=detect; initgraph(gd,gm,' ');
- INIT; cleardevice;
- for N:=1 to 32000 do
- begin
- MAKETRAN;
- putpixel(round(bx*xsc)+xoff,(round(asp*by*ysc)+yoff),green);
- end;
- readln; cleardevice; closegraph;
- END.
-
-